package com.habdqn.jspdemo.im.dao;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.*;

/**
 * 数据库操作的基类
 * 主要包含了三个对象，四个方法
 * @author
 */
public class BaseDao {

    /**
     * 通过标识名来创建相应连接池
     */
    static ComboPooledDataSource dataSource=new ComboPooledDataSource("mysql");

    private Connection conn;
    private PreparedStatement ps;
    protected ResultSet rs;


    /**
     * 抽象增删改的方法
     * @param sql 包含占位符的SQL
     * @param paras 参数数组
     * @return
     *
     * 类型后面加上"..."表示在该位置可以是0个到任意个对应类型的参数
     * 相当于以下方法的合并写法
     * 注意：这种写法只能在方法声明中的最后一个参数才行
     * public int executeUpdate(String sql)
     * public int executeUpdate(String sql,Object para1)
     * public int executeUpdate(String sql,Object para1,Object para2)
     * public int executeUpdate(String sql,Object para1,Object para2,Object para3)
     * ....
     */
    public int executeUpdate(String sql,Object... paras){
        int flag = -1;
        getConn();
        try {
            setParas(sql,paras);
            flag = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll();
        }
        return flag;
    }

    /**
     * 抽象查询方法
     * @param sql
     * @param paras
     * @return
     */
    public ResultSet executeQuery(String sql,Object... paras){
        getConn();
        try {
            setParas(sql,paras);
            rs = ps.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }

    /**
     * 获取唯一结果对象的方法
     * @param sql
     * @param paras
     * @return
     */
    public Object uniqueResult(String sql, Object... paras){
        getConn();
        try {
            setParas(sql,paras);
            rs = ps.executeQuery();
            while (rs.next()){
                return rs.getObject(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll();
        }
        return null;
    }


    /**
     * 获取C3P0数据源链接
     */
    public void getConn(){
        try {
            conn = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }



    /**
     * 通过Tomcat数据源获取数据库连接
     * 使用JNDI(Java Naming and Directory Interface)Java命名与目录接口服务
     */
//    public void getConn(){
//        try {
//            //初始化系统环境上下文
//            Context ctx = new InitialContext();
//            //从上下文中得到数据源对象（连接池）
//            DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/jspdemo");
//            //通过数据源获取数据库链接
//            conn = ds.getConnection();
//        } catch (NamingException | SQLException e) {
//            e.printStackTrace();
//        }
//    }

    /**
     * 通过DriverManager获取数据库连接
     */
//    public void getConn(){
//        try {
//            Class.forName("com.mysql.cj.jdbc.Driver");
//            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jspdemo?useUnicode=true&" +
//                    "characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai","root","root");
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
//
//    }

    /**
     * 关闭所有资源的操作
     */
    public void closeAll(){
        if(rs!=null){
            try {
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if(ps!=null){
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 提取ps绑定参数的操作
     */
    private void setParas(String sql, Object... paras) throws SQLException {
        ps = conn.prepareStatement(sql);
        if(paras!=null){
            for (int i = 0; i < paras.length; i++) {
                ps.setObject(i+1,paras[i]);
            }
        }
    }

}
